package ar.uba.fi.taller2.ftrs.parser;

import ar.uba.fi.taller2.ftrs.common.*;
import ar.uba.fi.taller2.ftrs.index.*;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.*;
import org.tartarus.snowball.SnowballProgram;


/**
 * @author  juampi
 */
public class Parser {
	
	private String pdl_key  ="PARSER_DEFAULT_LANGUAGE";
	private String pdff_key ="PARSER_DISMISSED_FRASES_FILE";
	private String dbg_key  ="PARSER_DEBUG";
	private String pswf_key ="PARSER_STOPWORDS_FILE";
	private Indexador indexador;
	
	protected String listaLocucionesPath;
	protected String defaultLanguage;	
	protected Pipe pipe;
	protected List<String> stopWords;
	protected boolean debug;
		
	public Parser(){
		
		this.indexador = Indexador.getIndexador();
		this.pipe = new Pipe();	
		this.stopWords = new ArrayList<String>();
		//Obtengo los parametros del Parser . 
		try	{
			this.pipe.cargarLocuciones(Parameters.getParametros().getMessage(pdff_key,1));
			this.defaultLanguage=Parameters.getParametros().getMessage(pdl_key,1);
			this.debug=Boolean.parseBoolean(Parameters.getParametros().getMessage(dbg_key,1));
			this.cargarStopWords(Parameters.getParametros().getMessage(pswf_key,1));
		}catch(Exception e)
			{
			this.debug = false;
			this.defaultLanguage="spanish";
		}
	}
	
	private String[] normalizarTexto(String texto){
		//Elimino los caracteres "-\n" 
		texto=texto.replaceAll("[-]{1}[\n]{1}","");
		//Reemplazo los caractres que no me interesan		
		texto=texto.replaceAll("[–\n \t\r\\|\"”'$鷿?¿!¡%/()=.,:;!@#ǩ-]{1}"," ");
		texto=texto.replaceAll("\\b\\s{2,}\\b", " ");
		// Paso el texto a Minùsculas
		texto=texto.toLowerCase();
		// Modifico las vocales acentuadas por vocal sin acento		
		texto=texto.replaceAll("[àá]","a");
		texto=texto.replaceAll("[èé]","e");
		texto=texto.replaceAll("[ìí]","i");
		texto=texto.replaceAll("[òó]","o");
		texto=texto.replaceAll("[ùú]","u");
		// Separo las palabras 
		return texto.split("[\n \t\r]");
	}
	
	private void cargarStopWords(String fileName) throws Exception{
		//Leo el Archivo
   	 	BufferedReader in = new BufferedReader(new FileReader(fileName));
   	 	if (!in.ready())
   	 		throw new IOException();
   	 	String line;	
   		while ( (line=in.readLine()) != null) {
			this.stopWords.add(line.trim());
		}		
	    in.close();
	}
	
	private boolean isStopWord(String palabra){		
		/* 
		 *   Listas de StopWords
		 *   http://www.web-mining.fr/wiki/stopwords/spanish
		 *   http://dev.swish-e.org/browser/branches/vendor/swish-e/conf/stopwords/spanish.txt?rev=3
		 *   http://www.elwebmaster.com/referencia/stopwords-en-espanol
		 *   http://www.ranks.nl/stopwords/spanish.html
		 *   http://snowball.tartarus.org/algorithms/spanish/stop.txt
		 * 
		 *   Recursos interesantes:
		 *   http://wwwdi.ujaen.es/asignaturas/il/
		 *   http://gate.ac.uk/
		 *   http://www.lemurproject.org/
		 *   http://www.mail-archive.com/lucene-user@jakarta.apache.org/msg09151.html
		 *   
		 */
		 if ( this.stopWords.contains((String)palabra) )
			 return true;
		 return false;
	}
	
	public String parsearConsulta(String lang,String consulta) throws Exception{
		ListaPalabras lp = procesarTexto(lang,consulta);	
		String respuesta=new String();
		String palabra;
		while((palabra=lp.next())!=null){
			//INDEXO PALABRA
			respuesta+=" "+palabra;
		}	
		return respuesta;
	}
	
	public String parsearConsulta(String consulta) throws Exception{
		return this.parsearConsulta(this.defaultLanguage);
	}
	
	private ListaPalabras procesarTexto(String lang,String texto)throws Exception{
		ListaPalabras lPalabras = new ListaPalabras();		
		// Inicializacion de librería de Stemming
		Class stemClass = Class.forName("org.tartarus.snowball.ext."+lang+"Stemmer");
		SnowballProgram stemmer = (SnowballProgram) stemClass.newInstance();
		Method stemMethod = stemClass.getMethod("stem", new Class[0]);		
		Object [] emptyArgs = new Object[0];		
		String tmpstring =texto;
		String palabraIngresada;
		String palabraExtraida;
		String palabraARetornar;		
		this.pipe.flushPipe();		
		
		// Normalizo el texto obtenido
		String[] palabras = normalizarTexto(tmpstring);
	
		for (int i = 0 ; i < palabras.length ; i++)
			{	
			  palabraIngresada = palabras[i].trim();
			  palabraExtraida = pipe.shift(palabraIngresada);
			  // Verifica que no sea una palabra comùn. si no lo es la agrega 
			  // para indexar, previo efectuar el stemming.
			  if (! isStopWord(palabraExtraida) && (palabraExtraida!=null) ){
				  stemmer.setCurrent(palabraExtraida);
				  stemMethod.invoke(stemmer, emptyArgs);
				  palabraARetornar = stemmer.getCurrent();			  
				  lPalabras.sumarOcurrencia(palabraARetornar);
			  }
			  
			  //Para propòsitos de debugging			  
			  //System.out.print(outString[i]+" \n"+" "+i);
			}
		return lPalabras;
	}
	
	public void parsear(String lang,String texto)throws Exception {
	// Este mètodo realiza el parseo de un string que recibe como parmetro
	// A este string le extrae las palabras raices a travès del algoritmo 
	// de Porter Stemmer y carga la estructura lPalabras con la cantidad que
	// aparece cada palabra raíz en el string recibido
		ListaPalabras lp = procesarTexto(lang,texto);	
		String palabraAIndexar;
		while((palabraAIndexar=lp.next())!=null){
			//INDEXO PALABRA
			indexador.insertarTermino(palabraAIndexar);
			indexador.insertarTermino(palabraAIndexar);
		}		
	}
	
	public void parsear(String texto)throws Exception{
		parsear(this.defaultLanguage,texto);
	}
	
	public void parsear()throws Exception{
		// Método para ser heredado por los Parsers de Archivos Específicos.
		// No cumple ninguna función en la clase Padre, por no tener datos de archivos.
	}
}
